"""
Author: Jian SuiYue kaohx0214@yeah.net
Date: 2025-04-23 00:43:42
LastEditTime: 2025-05-22 22:29:47
FilePath: LibraryManagerStudio/web/app.py
"""
import os.path
import sys
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager

from fastapi import FastAPI, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from loguru import logger

from .config import settings
from .deps import init_managers, cleanup_resources
from .initialization import AppInitializer
from .middlewares import request_handler_middleware
from .routes import admin_api, book_api, log_api, user_api, category_api, borrow_api, session_api, \
    message_api, friend_api
from ..version import VERSION

# 添加父目录到Python路径
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if parent_dir not in sys.path:
    sys.path.insert(0, parent_dir)

# 设置日志记录
app_file_path = os.path.dirname(os.path.abspath(__file__))
initializer = AppInitializer(settings, app_file_path)


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    """
    The fastapi application lifesapn
    """
    logger.info("Initializing the application...")

    # Initial manager
    await init_managers(initializer.database_uri, initializer.config_dir, initializer.app_root)

    # 任何其他初始化代码
    host = os.environ.get('LIBRARYADMINSTUDIO_HOST', '127.0.0.1')
    port = os.environ.get('LIBRARYADMINSTUDIO_PORT', '8081')
    logger.info(f"🐛Application start complete.Please visit http://{host}:{port}/{VERSION}/api/docs")

    yield

    # close 
    try:
        logger.info("Cleaning the application resources...")
        await cleanup_resources()
    except Exception as e:
        logger.error(f"Error failed at close application: {str(e)}")
    finally:
        logger.info("Application close success!")


# Create fastapi application
app = FastAPI(
    title="Library Manager Studio",
    description="Library Manager Studio",
    version=VERSION,
    lifespan=lifespan,
    docs_url="/docs" if settings.API_DOCS else None,
    debug=True,
)

# add cros middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"
                   "http://127.0.0.1:8000"
                   "http://127.0.0.1:8081"
                   #"https://www.jiansy.asia:8081" WARNING: 在我服务器备案完成前不要关闭此注释
                   #Warning: Do not close this comment until my server registration is complete.
                   ],  # limit domain who can send request to my application
    allow_credentials=True,
    allow_methods=["*"],  # limit the request method 
    allow_headers=["*"],
)

# 添加请求处理中间件
app.middleware("http")(request_handler_middleware)


# add exception handleer
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    """Process the requset verify error"""
    errors = []
    for error in exc.errors():
        errors.append({
            "loc": error.get("loc", []),
            "msg": error.get("msg", ""),
            "type": error.get("type", "")
        })
    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content={"message": "request params verfiy failed", "status": False, "errors": errors},
    )


@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
    """Process the general exception"""
    logger.error(f"Unhandled exception: {str(exc)}", exc_info=True)
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content={"message": "Server error, please contact the administrator.", "status": False},
    )


# Create API router with version and documentation
api = FastAPI(
    root_path=f"/{VERSION}/api",
    title="Library Manager Studio API",
    version=VERSION,
    description="Library Manager Studio",
    docs_url="/docs" if settings.API_DOCS else None,
)

# register or mount the router

api.include_router(
    admin_api.router,
    prefix="/admin",
    tags=["admin"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    book_api.router,
    prefix="/books",
    tags=["books"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    category_api.router,
    prefix="/category",
    tags=["category"],
    responses={404: {"description": "Not found"}}
)

api.include_router(
    log_api.router,
    prefix="/logs",
    tags=["logs"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    user_api.router,
    prefix="/users",
    tags=["users"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    borrow_api.router,
    prefix="/borrows",
    tags=["borrows"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    session_api.router,
    prefix="/sessions",
    tags=["sessions"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    message_api.router,
    prefix="/messages",
    tags=["messages"],
    responses={404: {"description": "Not found"}},
)

api.include_router(
    friend_api.router,
    prefix="/friends",
    tags=["friends"],
    responses={404: {"description": "Not found"}},
)


# add chekc helath path
@api.get("/health", tags=["system"])
async def health_check():
    """API健康检查端点"""
    return {"status": "healthy"}




static_path = os.path.join(app_file_path, 'static')
api.mount("/static/book", StaticFiles(directory=f"{os.path.join(static_path, 'book')}"), name="book")
api.mount("/static/avatar", StaticFiles(directory=f"{os.path.join(static_path, 'avatar')}"), name="avatar")
api.mount("/static/icon", StaticFiles(directory=f"{os.path.join(static_path, 'icon')}"), name="icon")
app.mount(f"/{VERSION}/api", api)
app.mount(
    "/files",
    StaticFiles(directory=initializer.static_root, html=True),
    name="files",
)

# add get version path
@app.get("/version", tags=["system"])
async def get_version():
    """获取API版本信息"""
    return {"version": VERSION}

@app.get("/")
async def test():
    return "Hello world!"


def create_app() -> FastAPI:
    """
    Factory function to create and configure the FastAPI application.
    Useful for testing and different deployment scenarios.
    """
    return app
